; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py
; RUN: opt -disable-output "-passes=print<scalar-evolution>" < %s 2>&1 | FileCheck %s

define ptr @pointer_select_two_objects(i1 %cond, ptr %first_obj, ptr %second_obj) {
; CHECK-LABEL: 'pointer_select_two_objects'
; CHECK-NEXT:  Classifying expressions for: @pointer_select_two_objects
; CHECK-NEXT:    %r = select i1 %cond, ptr %first_obj, ptr %second_obj
; CHECK-NEXT:    --> %r U: full-set S: full-set
; CHECK-NEXT:  Determining loop execution counts for: @pointer_select_two_objects
;
  %r = select i1 %cond, ptr %first_obj, ptr %second_obj
  ret ptr %r
}

;--

define ptr @pointer_select_same_object_constant_offsets(i1 %cond, ptr %obj) {
; CHECK-LABEL: 'pointer_select_same_object_constant_offsets'
; CHECK-NEXT:  Classifying expressions for: @pointer_select_same_object_constant_offsets
; CHECK-NEXT:    %true_ptr = getelementptr i8, ptr %obj, i64 42
; CHECK-NEXT:    --> (42 + %obj) U: full-set S: full-set
; CHECK-NEXT:    %false_ptr = getelementptr i8, ptr %obj, i64 24
; CHECK-NEXT:    --> (24 + %obj) U: full-set S: full-set
; CHECK-NEXT:    %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
; CHECK-NEXT:    --> %r U: full-set S: full-set
; CHECK-NEXT:  Determining loop execution counts for: @pointer_select_same_object_constant_offsets
;
  %true_ptr = getelementptr i8, ptr %obj, i64 42
  %false_ptr = getelementptr i8, ptr %obj, i64 24
  %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
  ret ptr %r
}

define ptr @pointer_select_same_object_variable_offsets(i1 %cond, ptr %obj, i64 %true_off, i64 %false_off) {
; CHECK-LABEL: 'pointer_select_same_object_variable_offsets'
; CHECK-NEXT:  Classifying expressions for: @pointer_select_same_object_variable_offsets
; CHECK-NEXT:    %true_ptr = getelementptr i8, ptr %obj, i64 %true_off
; CHECK-NEXT:    --> (%true_off + %obj) U: full-set S: full-set
; CHECK-NEXT:    %false_ptr = getelementptr i8, ptr %obj, i64 %false_off
; CHECK-NEXT:    --> (%false_off + %obj) U: full-set S: full-set
; CHECK-NEXT:    %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
; CHECK-NEXT:    --> %r U: full-set S: full-set
; CHECK-NEXT:  Determining loop execution counts for: @pointer_select_same_object_variable_offsets
;
  %true_ptr = getelementptr i8, ptr %obj, i64 %true_off
  %false_ptr = getelementptr i8, ptr %obj, i64 %false_off
  %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
  ret ptr %r
}

define ptr @pointer_select_same_object_constant_offset_vs_variable_offset(i1 %cond, ptr %obj, i64 %false_off) {
; CHECK-LABEL: 'pointer_select_same_object_constant_offset_vs_variable_offset'
; CHECK-NEXT:  Classifying expressions for: @pointer_select_same_object_constant_offset_vs_variable_offset
; CHECK-NEXT:    %true_ptr = getelementptr i8, ptr %obj, i64 42
; CHECK-NEXT:    --> (42 + %obj) U: full-set S: full-set
; CHECK-NEXT:    %false_ptr = getelementptr i8, ptr %obj, i64 %false_off
; CHECK-NEXT:    --> (%false_off + %obj) U: full-set S: full-set
; CHECK-NEXT:    %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
; CHECK-NEXT:    --> %r U: full-set S: full-set
; CHECK-NEXT:  Determining loop execution counts for: @pointer_select_same_object_constant_offset_vs_variable_offset
;
  %true_ptr = getelementptr i8, ptr %obj, i64 42
  %false_ptr = getelementptr i8, ptr %obj, i64 %false_off
  %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
  ret ptr %r
}

define ptr @pointer_select_same_object_variable_offset_vs_constant_offset(i1 %cond, ptr %obj, i64 %true_off) {
; CHECK-LABEL: 'pointer_select_same_object_variable_offset_vs_constant_offset'
; CHECK-NEXT:  Classifying expressions for: @pointer_select_same_object_variable_offset_vs_constant_offset
; CHECK-NEXT:    %true_ptr = getelementptr i8, ptr %obj, i64 %true_off
; CHECK-NEXT:    --> (%true_off + %obj) U: full-set S: full-set
; CHECK-NEXT:    %false_ptr = getelementptr i8, ptr %obj, i64 42
; CHECK-NEXT:    --> (42 + %obj) U: full-set S: full-set
; CHECK-NEXT:    %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
; CHECK-NEXT:    --> %r U: full-set S: full-set
; CHECK-NEXT:  Determining loop execution counts for: @pointer_select_same_object_variable_offset_vs_constant_offset
;
  %true_ptr = getelementptr i8, ptr %obj, i64 %true_off
  %false_ptr = getelementptr i8, ptr %obj, i64 42
  %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
  ret ptr %r
}

;--

define ptr @pointer_select_same_object_with_constant_base_offset__constant_offsets(i1 %cond, ptr %obj.base) {
; CHECK-LABEL: 'pointer_select_same_object_with_constant_base_offset__constant_offsets'
; CHECK-NEXT:  Classifying expressions for: @pointer_select_same_object_with_constant_base_offset__constant_offsets
; CHECK-NEXT:    %obj = getelementptr i8, ptr %obj.base, i64 12
; CHECK-NEXT:    --> (12 + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %true_ptr = getelementptr i8, ptr %obj, i64 42
; CHECK-NEXT:    --> (54 + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %false_ptr = getelementptr i8, ptr %obj, i64 24
; CHECK-NEXT:    --> (36 + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
; CHECK-NEXT:    --> %r U: full-set S: full-set
; CHECK-NEXT:  Determining loop execution counts for: @pointer_select_same_object_with_constant_base_offset__constant_offsets
;
  %obj = getelementptr i8, ptr %obj.base, i64 12
  %true_ptr = getelementptr i8, ptr %obj, i64 42
  %false_ptr = getelementptr i8, ptr %obj, i64 24
  %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
  ret ptr %r
}

define ptr @pointer_select_same_object_with_constant_base_offset__variable_offsets(i1 %cond, ptr %obj.base, i64 %true_off, i64 %false_off) {
; CHECK-LABEL: 'pointer_select_same_object_with_constant_base_offset__variable_offsets'
; CHECK-NEXT:  Classifying expressions for: @pointer_select_same_object_with_constant_base_offset__variable_offsets
; CHECK-NEXT:    %obj = getelementptr i8, ptr %obj.base, i64 12
; CHECK-NEXT:    --> (12 + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %true_ptr = getelementptr i8, ptr %obj, i64 %true_off
; CHECK-NEXT:    --> (12 + %true_off + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %false_ptr = getelementptr i8, ptr %obj, i64 %false_off
; CHECK-NEXT:    --> (12 + %false_off + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
; CHECK-NEXT:    --> %r U: full-set S: full-set
; CHECK-NEXT:  Determining loop execution counts for: @pointer_select_same_object_with_constant_base_offset__variable_offsets
;
  %obj = getelementptr i8, ptr %obj.base, i64 12
  %true_ptr = getelementptr i8, ptr %obj, i64 %true_off
  %false_ptr = getelementptr i8, ptr %obj, i64 %false_off
  %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
  ret ptr %r
}

define ptr @pointer_select_same_object_with_constant_base_offset__constant_offset_vs_variable_offset(i1 %cond, ptr %obj.base, i64 %false_off) {
; CHECK-LABEL: 'pointer_select_same_object_with_constant_base_offset__constant_offset_vs_variable_offset'
; CHECK-NEXT:  Classifying expressions for: @pointer_select_same_object_with_constant_base_offset__constant_offset_vs_variable_offset
; CHECK-NEXT:    %obj = getelementptr i8, ptr %obj.base, i64 12
; CHECK-NEXT:    --> (12 + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %true_ptr = getelementptr i8, ptr %obj, i64 42
; CHECK-NEXT:    --> (54 + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %false_ptr = getelementptr i8, ptr %obj, i64 %false_off
; CHECK-NEXT:    --> (12 + %false_off + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
; CHECK-NEXT:    --> %r U: full-set S: full-set
; CHECK-NEXT:  Determining loop execution counts for: @pointer_select_same_object_with_constant_base_offset__constant_offset_vs_variable_offset
;
  %obj = getelementptr i8, ptr %obj.base, i64 12
  %true_ptr = getelementptr i8, ptr %obj, i64 42
  %false_ptr = getelementptr i8, ptr %obj, i64 %false_off
  %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
  ret ptr %r
}

define ptr @pointer_select_same_object_with_constant_base_offset__variable_offset_vs_constant_offset(i1 %cond, ptr %obj.base, i64 %true_off) {
; CHECK-LABEL: 'pointer_select_same_object_with_constant_base_offset__variable_offset_vs_constant_offset'
; CHECK-NEXT:  Classifying expressions for: @pointer_select_same_object_with_constant_base_offset__variable_offset_vs_constant_offset
; CHECK-NEXT:    %obj = getelementptr i8, ptr %obj.base, i64 12
; CHECK-NEXT:    --> (12 + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %true_ptr = getelementptr i8, ptr %obj, i64 %true_off
; CHECK-NEXT:    --> (12 + %true_off + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %false_ptr = getelementptr i8, ptr %obj, i64 42
; CHECK-NEXT:    --> (54 + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
; CHECK-NEXT:    --> %r U: full-set S: full-set
; CHECK-NEXT:  Determining loop execution counts for: @pointer_select_same_object_with_constant_base_offset__variable_offset_vs_constant_offset
;
  %obj = getelementptr i8, ptr %obj.base, i64 12
  %true_ptr = getelementptr i8, ptr %obj, i64 %true_off
  %false_ptr = getelementptr i8, ptr %obj, i64 42
  %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
  ret ptr %r
}

;--

define ptr @pointer_select_same_object_with_variable_base_offset__constant_offsets(i1 %cond, ptr %obj.base, i64 %base_offset) {
; CHECK-LABEL: 'pointer_select_same_object_with_variable_base_offset__constant_offsets'
; CHECK-NEXT:  Classifying expressions for: @pointer_select_same_object_with_variable_base_offset__constant_offsets
; CHECK-NEXT:    %obj = getelementptr i8, ptr %obj.base, i64 %base_offset
; CHECK-NEXT:    --> (%base_offset + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %true_ptr = getelementptr i8, ptr %obj, i64 42
; CHECK-NEXT:    --> (42 + %base_offset + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %false_ptr = getelementptr i8, ptr %obj, i64 24
; CHECK-NEXT:    --> (24 + %base_offset + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
; CHECK-NEXT:    --> %r U: full-set S: full-set
; CHECK-NEXT:  Determining loop execution counts for: @pointer_select_same_object_with_variable_base_offset__constant_offsets
;
  %obj = getelementptr i8, ptr %obj.base, i64 %base_offset
  %true_ptr = getelementptr i8, ptr %obj, i64 42
  %false_ptr = getelementptr i8, ptr %obj, i64 24
  %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
  ret ptr %r
}

define ptr @pointer_select_same_object_with_variable_base_offset__variable_offsets(i1 %cond, ptr %obj.base, i64 %base_offset, i64 %true_off, i64 %false_off) {
; CHECK-LABEL: 'pointer_select_same_object_with_variable_base_offset__variable_offsets'
; CHECK-NEXT:  Classifying expressions for: @pointer_select_same_object_with_variable_base_offset__variable_offsets
; CHECK-NEXT:    %obj = getelementptr i8, ptr %obj.base, i64 %base_offset
; CHECK-NEXT:    --> (%base_offset + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %true_ptr = getelementptr i8, ptr %obj, i64 %true_off
; CHECK-NEXT:    --> (%base_offset + %true_off + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %false_ptr = getelementptr i8, ptr %obj, i64 %false_off
; CHECK-NEXT:    --> (%base_offset + %false_off + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
; CHECK-NEXT:    --> %r U: full-set S: full-set
; CHECK-NEXT:  Determining loop execution counts for: @pointer_select_same_object_with_variable_base_offset__variable_offsets
;
  %obj = getelementptr i8, ptr %obj.base, i64 %base_offset
  %true_ptr = getelementptr i8, ptr %obj, i64 %true_off
  %false_ptr = getelementptr i8, ptr %obj, i64 %false_off
  %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
  ret ptr %r
}

define ptr @pointer_select_same_object_with_variable_base_offset__constant_offset_vs_variable_offset(i1 %cond, ptr %obj.base, i64 %base_offset, i64 %false_off) {
; CHECK-LABEL: 'pointer_select_same_object_with_variable_base_offset__constant_offset_vs_variable_offset'
; CHECK-NEXT:  Classifying expressions for: @pointer_select_same_object_with_variable_base_offset__constant_offset_vs_variable_offset
; CHECK-NEXT:    %obj = getelementptr i8, ptr %obj.base, i64 %base_offset
; CHECK-NEXT:    --> (%base_offset + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %true_ptr = getelementptr i8, ptr %obj, i64 42
; CHECK-NEXT:    --> (42 + %base_offset + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %false_ptr = getelementptr i8, ptr %obj, i64 %false_off
; CHECK-NEXT:    --> (%base_offset + %false_off + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
; CHECK-NEXT:    --> %r U: full-set S: full-set
; CHECK-NEXT:  Determining loop execution counts for: @pointer_select_same_object_with_variable_base_offset__constant_offset_vs_variable_offset
;
  %obj = getelementptr i8, ptr %obj.base, i64 %base_offset
  %true_ptr = getelementptr i8, ptr %obj, i64 42
  %false_ptr = getelementptr i8, ptr %obj, i64 %false_off
  %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
  ret ptr %r
}

define ptr @pointer_select_same_object_with_variable_base_offset__variable_offset_vs_constant_offset(i1 %cond, ptr %obj.base, i64 %base_offset, i64 %true_off) {
; CHECK-LABEL: 'pointer_select_same_object_with_variable_base_offset__variable_offset_vs_constant_offset'
; CHECK-NEXT:  Classifying expressions for: @pointer_select_same_object_with_variable_base_offset__variable_offset_vs_constant_offset
; CHECK-NEXT:    %obj = getelementptr i8, ptr %obj.base, i64 %base_offset
; CHECK-NEXT:    --> (%base_offset + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %true_ptr = getelementptr i8, ptr %obj, i64 %true_off
; CHECK-NEXT:    --> (%base_offset + %true_off + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %false_ptr = getelementptr i8, ptr %obj, i64 42
; CHECK-NEXT:    --> (42 + %base_offset + %obj.base) U: full-set S: full-set
; CHECK-NEXT:    %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
; CHECK-NEXT:    --> %r U: full-set S: full-set
; CHECK-NEXT:  Determining loop execution counts for: @pointer_select_same_object_with_variable_base_offset__variable_offset_vs_constant_offset
;
  %obj = getelementptr i8, ptr %obj.base, i64 %base_offset
  %true_ptr = getelementptr i8, ptr %obj, i64 %true_off
  %false_ptr = getelementptr i8, ptr %obj, i64 42
  %r = select i1 %cond, ptr %true_ptr, ptr %false_ptr
  ret ptr %r
}
